package com.qunar.train.mock.config;

import com.qunar.train.mock.util.AegisLog;
import com.qunar.train.mock.util.SpringUtil;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class ResetFieldUtil {

    //use reflection to override the Method content and add to static
    public static void resetField(Class clazz, String fieldName, Object fieldValue) {

        try {
            //获取属性并设置属性
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            Boolean isStatic = resetFieldModifiers(field);

            if (!isStatic) {
                if (MockQconfig.qconfigSwitch) {
                    field.set(SpringUtil.getBean(clazz), fieldValue);
                } else {
                    ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:test.xml");
                    field.set(ac.getBean(clazz), fieldValue);
                }

            } else {
                //修改静态属性值
                field.set(null, fieldValue);
            }

        } catch (Exception e) {
            AegisLog.error(e);
        }
    }

    //适用于一般的情况，传入一个实例
    public static void resetField(Object o, String fieldName, Object fieldValue) {
        try {
            Class<?> clazz = o.getClass();
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);

            Boolean isStatic = resetFieldModifiers(field);
            if (field != null) {
                if (!isStatic) {

                    field.set(o, fieldValue);
                } else {
                    //修改静态属性值
                    field.set(null, fieldValue);
                }
            }

        } catch (Exception e) {
            AegisLog.error(e);
        }
    }

    private static Boolean resetFieldModifiers(Field field) {
        Boolean isStatic = false;
        try {
            //Filed类
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);

            //获取修饰符算子并去除final并添加static修饰符
            int modifiers = modifiersField.getInt(field);
            modifiers &= ~Modifier.FINAL;
            modifiersField.setInt(field, modifiers);
            isStatic = Modifier.isStatic(modifiers);
        } catch (NoSuchFieldException e) {
            AegisLog.error(e);
        } catch (IllegalAccessException e) {
            AegisLog.error(e);
        }
        return isStatic;
    }
}
